﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;

namespace Epic.ComponentServices
{
    public class BasicPropertyOrderConverter : ExpandableObjectConverter
    {
#pragma warning disable 1591

        private static BasicPropertyOrderConverter smInstance = new BasicPropertyOrderConverter();
        public static BasicPropertyOrderConverter Instance { get { return smInstance; } }

        public static Comparer ComparerInstance { get { return Comparer.Instance; } }

        public class Comparer : IComparer<PropertyDescriptor>, IComparer
        {
            private static Comparer smInstance = new Comparer();
            public static Comparer Instance
            {
                get { return smInstance; }
            }

            public int Compare(object x, object y)
            {
                return Compare((PropertyDescriptor)x, (PropertyDescriptor)y);
            }
            public int Compare(PropertyDescriptor x, PropertyDescriptor y)
            {
                var result = InternalCompare(x, y);
                System.Diagnostics.Debug.WriteLine(x.Name + " : " + y.Name + " = " + result);
                return result;
            }
            public double InternalGetOrder(PropertyDescriptor prop)
            {
                var mo = prop.Attributes[typeof(MemberOrderAttribute)] as MemberOrderAttribute;
                if (null != mo)
                    return mo.Order;

                return double.NaN;
            }
            public int InternalCompare(PropertyDescriptor x, PropertyDescriptor y)
            {
                var orderA = InternalGetOrder(x);
                var orderB = InternalGetOrder(y);

                #region 比较两个属性的优先级
                if (double.IsNaN(orderA))
                {
                    // 如果两边都没有定义排序优先级，就按照名称来排序
                    if (double.IsNaN(orderB))
                        return string.Compare(x.DisplayName, y.DisplayName);

                    // 定义 B 且没有定义 A 的情况，则认为 B 优先
                    return 1;
                }
                else
                {
                    // 定义 A 且没有定义 B 的情况，则认为 A 优先
                    if (double.IsNaN(orderB)) return -1;

                    // 两者都有定义的情况，就直接进行数值比较
                    return orderA.CompareTo(orderB);
                }
                #endregion
            }
        }

        public static PropertyDescriptorCollection Sort(PropertyDescriptorCollection collection)
        {
            return collection.Sort(ComparerInstance);
        }

        public override bool GetPropertiesSupported(ITypeDescriptorContext context)
        { return true; }
        public override PropertyDescriptorCollection GetProperties(ITypeDescriptorContext context, object value, Attribute[] attributes)
        {
            PropertyDescriptorCollection pdc;
            if (attributes == null)
                pdc = TypeDescriptor.GetProperties(value);
            else
                pdc = TypeDescriptor.GetProperties(value, attributes);

            // 进行排序，是覆写 GetProperties 的唯一目的
            return Sort(pdc);
            // TODO: why!?
            //return pdc.Sort(Comparer.Instance);
        }
    }
}
